/**
 * Shared Matter Validation Utilities
 *
 * Common validation functions used across Matter configuration validators
 * to ensure consistency and reduce duplication.
 */

import { Logger } from '../logger.js'

const log = Logger.withPrefix('Matter')

/**
 * Port validation result
 */
export interface PortValidationResult {
  valid: boolean
  error?: string
  warning?: string
}

/**
 * Sanitization result
 */
export interface SanitizationResult<T> {
  value: T
  warnings: string[]
}

/**
 * Validate a Matter port number
 *
 * @param port - Port number to validate
 * @param checkConflicts - Whether to check for known conflicting ports
 * @returns Validation result with error/warning messages
 */
export function validatePort(port: number, checkConflicts = false): PortValidationResult {
  if (!Number.isInteger(port)) {
    return { valid: false, error: `Port must be an integer (got: ${port})` }
  }

  if (port < 1025 || port > 65534) {
    return { valid: false, error: `Port must be between 1025 and 65534 (got: ${port})` }
  }

  // Check for common conflicts
  if (checkConflicts) {
    const conflictPorts = [5353, 8080, 8443] // mDNS, common HTTP ports
    if (conflictPorts.includes(port)) {
      return {
        valid: true,
        warning: `Port ${port} may conflict with other services. Consider using a different port.`,
      }
    }
  }

  return { valid: true }
}

/**
 * Sanitize a unique ID to be filesystem-safe
 *
 * Replaces non-alphanumeric characters with hyphens, collapses multiple hyphens,
 * trims leading/trailing hyphens, and converts to lowercase.
 *
 * @param uniqueId - Unique identifier to sanitize
 * @returns Sanitized unique ID and any warnings
 */
export function sanitizeUniqueId(uniqueId: string): SanitizationResult<string> {
  const warnings: string[] = []
  const original = uniqueId

  if (uniqueId.trim().length === 0) {
    return {
      value: '',
      warnings: ['uniqueId is empty after trimming'],
    }
  }

  const sanitized = uniqueId
    .replace(/[^a-z0-9]/gi, '-') // Replace non-alphanumeric with hyphens
    .replace(/-+/g, '-') // Collapse multiple hyphens
    .replace(/^-|-$/g, '') // Trim leading/trailing hyphens
    .toLowerCase() // Lowercase for consistency

  if (sanitized !== original) {
    warnings.push(`uniqueId was sanitized from "${original}" to "${sanitized}"`)
  }

  if (sanitized.length === 0) {
    warnings.push('uniqueId resulted in empty string after sanitization')
  }

  return { value: sanitized, warnings }
}

/**
 * Truncate a string to a maximum length with warning
 *
 * @param value - String to truncate
 * @param maxLength - Maximum allowed length
 * @param fieldName - Name of the field (for warnings)
 * @returns Truncated value and any warnings
 */
export function truncateString(
  value: string,
  maxLength: number,
  fieldName: string,
): SanitizationResult<string> {
  const warnings: string[] = []

  if (value.length > maxLength) {
    warnings.push(`${fieldName} exceeds ${maxLength} characters, truncating: ${value}`)
    log.warn(`${fieldName} exceeds ${maxLength} characters, truncating: ${value}`)
    return {
      value: value.slice(0, maxLength),
      warnings,
    }
  }

  return { value, warnings }
}

/**
 * Check for port conflicts between HAP and Matter ports
 *
 * @param hapPort - HAP bridge port
 * @param matterPort - Matter bridge port
 * @returns Warning message if ports are too close, undefined otherwise
 */
export function checkPortProximity(hapPort: number, matterPort: number): string | undefined {
  const MIN_PORT_SEPARATION = 10

  if (Math.abs(hapPort - matterPort) < MIN_PORT_SEPARATION) {
    return `HAP port ${hapPort} and Matter port ${matterPort} are very close. Consider spacing them further apart.`
  }

  return undefined
}
